;  PROGRAM:  SAK (Strike Any Key)
;  AUTHOR:  Richard Conn
;  VERSION:  2.2
;  DATE:  1 October 85
;  PREVIOUS VERSIONS:  1.0 (18 Apr 83), 2.0 (18 May 84), 2.1 (8 June 85)

; Version 22a - added screen highlighting to built-in help msg.
;                                21 August 1986 - Frank Gaude'

vers	equ	22	; Changed to allow the BIOS to return from
			; CONIN: with the zero flag set.  CONDIN:
			; subroutine in SYSLIB assumes, incorrectly,
			; this flag will always be non-zero.
			;        Joe Wright  21 September 1985
			;        program updated by Ken Davidson
z3env	set	0fe00h

;
;	SAK (Strike Any Key) is used for the following purposes:
;		1) to wait for user interaction before continuing
;			and to allow the user to abort a Multiple
;			Command Line
;		2) to command the user's attention by ringing the
;			bell at his console
;		3) abort ZEX command file in execution (2.1 - RLC)
;
;	The SAK command line is:
;		SAK o...
;	SAK is invoked with the following options:
;		A     -- DO NOT Allow the User to Abort MCL
;		B     -- Ring Bell
;		Pnnnn -- Pause nnnn seconds and continue if no
;			 response by that time
;		Z     -- Allow the User to Abort ZEX
;
	ext	z3vinit,wait1s,getcl1,qprint,qcrlf
	ext	strtzex,stopzex,putzex,getznc,getzrun
	ext	pstr,print,vprint,cst,cin,eval10,cout

tbuff	equ	80h	;command line buffer
cr	equ	0dh
lf	equ	0ah
ctrlc	equ	'C'-'@'
ctrlg	equ	'G'-'@'
dim	equ	1
bright  equ	2

;
; Environment Definition
;
	if	z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
	jp	start
	db	'Z3ENV'	;This is a ZCPR3 Utility
	db	1	;External Environment Descriptor
z3eadr:
	dw	z3env
start:
	ld	hl,(z3eadr)	;pt to ZCPR3 environment
;
	else
;
; Internal ZCPR3 Environment Descriptor
;
	MACLIB	Z3BASE.LIB
	MACLIB	SYSENV.LIB
z3eadr:
	jp	start
	SYSENV
start:
	ld	hl,z3eadr	;pt to ZCPR3 environment
	endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
	call	z3vinit	;initialize the ZCPR3 Env and the VLIB Env

;  Init Options and Parse and Interpret Command Line
;
	xor	a	;turn options off
	ld	(mpflag),a	;turn off message printed flag
	ld	(bell),a	;turn off bell
	ld	(delay),a	;turn off delay (pause)
	ld	(delay+1),a
	ld	(stopz),a	;(2.1 - RLC) do not abort ZEX
	ld	a,0ffh	        ;turn options on
	ld	(abortf),a	;turn on abort
	ld	hl,tbuff+1	;pt to command line
spskp:
	ld	a,(hl)	;skip leading spaces
	inc	hl
	cp	' '
	jp	z,spskp
	dec	hl	;pt to char
	cp	'/'	;option?
	jp	nz,optdone
	inc	hl	;skip option char
opt:
	ld	a,(hl)	;get option letter
	or	a	;done?
	jp	z,optdone
	inc	hl	;pt to next
	cp	' '	;process text
	jp	z,optdone
	cp	'A'	;abort?
	jp	z,optabort
	cp	'B'	;bell?
	jp	z,optbell
	cp	'P'	;pause?
	jp	z,optpause
	cp	'Z'	;(2.1 - RLC) ZEX abort?
	jp	z,optzex
	call	vprint
	db	'SAK, Version ',[vers/10]+'0','.',[vers mod 10]+'0'
	db	cr,lf,dim,'Syntax:',bright,cr,lf
	db	'   SAK /o... text',dim,' -or- ',bright,'SAK text'
	db	cr,lf,dim,'Options:',bright,cr,lf
	db	' A     -- ',dim,'DO NOT Allow Abort',bright,cr,lf
	db	' B     -- ',dim,'Ring Bell',bright,cr,lf
	db	' Pnnnn -- ',dim,'Pause',bright,' nnnn ',dim,'secs'
	db	bright,cr,lf
	db	' Z     -- ',dim,'Allow to Abort ZEX',bright,cr,lf
	db	0
	ret

;
;  Process A option (Abort MCL)
;
optabort:
	xor	a	;turn off abort
	ld	(abortf),a
	jp	opt
;
;  Process B option (Ring Bell)
;
optbell:
	ld	a,0ffh	;turn on bell
	ld	(bell),a
	jp	opt
;
;  Process Pnnnn option (Pause nnnn seconds)
;
optpause:
	call	eval10	;convert argument to decimal value in DE
	ex	de,hl		;HL contains value
	ld	(delay),hl
	ex	de,hl		;HL pts to next char
	jp	opt
;
;  (2.1 - RLC) Process Z option (Allow ZEX abort)
;
optzex:
	ld	a,0ffh	;allow abort
	ld	(stopz),a
	jp	opt
;
;  Continue Command Processing
;
optdone:
	ld	a,(hl)	;any message?
	or	a
	jp	z,optdn1
	ld	(mpflag),a	;set message printed flag
	call	print	;new line
	db	'  --> ',0
	call	pstr	;print message
	call	print
	db	' <--  ',0
optdn1:
	call	stopzex	;suspend ZEX processing
	ld	hl,(delay)	;get delay count in HL
;
;  Main Delay Loop
;
sakloop:
;
;  Ring Bell if Option Selected
;
	ld	a,(bell)	;get flag
	or	a	;set zero flag
	call	nz,bout	;ring bell and delay
;
;  Get character if one is available
;
;	call	condin	;optionally get character
;	jp	nz,gotchar	;process character
;
;  This change in case the BIOS CONIN: returns with zero flag set.
;
	call	cst
	jr	nz,nochar
getchar:
	call	cin
	jp	gotchar
nochar:

;  Loop if No Delay
;
	ld	a,h	;check for no delay
	or	l
	jp	z,sakloop
;
;  Delay and test for input
;
	call	wait1s	;delay 1 sec
	dec	hl	;count down
	ld	a,h	;done?
	or	l
	jp	nz,sakloop
;
;  Process Input Character
;	If no input and timout instead, A=0 for continuation character
;
gotchar:
	cp	ctrlc	;abort?
	jp	z,abort
resume:
	ld	a,(mpflag)	;message printed?
	or	a	;0=no
	call	nz,qcrlf	;new line if yes
	call	qprint
	db	'Resuming ...',0
	jp	strtzex	;resume ZEX processing
;
;  Abort Multiple Command Line if there is one
;
abort:
	ld	a,(abortf)	;abort allowed?
	or	a	;0=no
	jp	z,resume
	call	getcl1	;get address of command line buffer
	ld	a,h	;any buffer?
	or	l
	jp	z,abort1
	ld	e,(hl)	;get address of next char
	inc	hl
	ld	d,(hl)
	ex	de,hl		;HL pts to next char
	ld	(hl),0	;set no further command
abort1:
	ld	a,(mpflag)	;message printed?
	or	a	;0=no
	call	nz,qcrlf	;new line if yes
	call	qprint
	db	'Aborting ...',0
	call	getzrun	;(2.1 - RLC) is ZEX running?
	ret	z		;(2.1 - RLC) done if not
	call	strtzex	;(2.1 - RLC) resume ZEX processing
	ld	a,(stopz)	;(2.1 - RLC) stop ZEX?
	or	a	;(2.1 - RLC) 0=no
	ret	z		;(2.1 - RLC) resume processing
	call	getznc	;(2.1 - RLC) get next ZEX char
	ld	(hl),0ffh	;(2.1 - RLC) store abort ZEX code
	ret

;
;  Ring Bell and Delay Briefly
;
bout:
	ld	a,ctrlg	;ring bell
	call	cout
	push	hl	;save HL
	ld	hl,(delay)	;do not delay if pause already invoked
	ld	a,h	;zero delay?
	or	l
	jp	nz,bout1	;skip delay
	call	wait1s	;delay
bout1:
	pop	hl
	ret

;
;  Other Buffers
;
abortf:
	ds	1	;abort flag
bell:
	ds	1	;bell flag
delay:
	ds	2	;delay constant
mpflag:
	ds	1	;message printed flag
stopz:
	ds	1	;(2.1 - RLC) stop ZEX flag

	end
l flag
delay:
	ds	2	;delay constant
mpflag:
	ds	1	;message printed flag
stopz:
	ds	1	;(2.1 - RLC) stop ZEX flag

	e